﻿#ifndef _BASETYPE_H
#define _BASETYPE_H

#include <string.h>
#include <new>

using namespace std;

namespace TypesLib
{

template<typename T>
inline T& AutoPopTypeRef(char* &aBuffer)
{
    T& TempRef = *((T*)aBuffer);
    aBuffer += sizeof(T);
    return TempRef;
}

template<typename T>
inline T& popWriteTypeRefFromBuffer(char* aBuffer)
{
    return *((T*)aBuffer);
}

template<typename T>
inline void PushTypeFromBuffer(char* aBuffer, T& aData)
{
    *((T*)aBuffer) = aData;
}

template<typename T>
class DVector
{
    const static int DVECTOR_INC_SIZE = 100;

public:
    DVector(int ASize = 0)
    {
        m_buffer = NULL;
        m_size = 0;
        m_top = 0;

        reAlloc(ASize);
    }

    ~DVector()
    {
        if(NULL != m_buffer)
        {
            delete []m_buffer;
        }

        m_buffer = NULL;
        m_size = 0;
        m_top = 0;
    }

    

    const T*  getBuffer()
    {
        return m_buffer;
    }

    void    push_back(T AT)
    {
        if(m_top >= m_size)
        {
            reAlloc(m_size + DVECTOR_INC_SIZE);
        }

        if(m_top < m_size)
        {
            m_buffer[m_top] = AT;
            ++m_top;
        }
    }

    T*   pop_back()
    {
        T* ret = NULL;
        if(m_top > 0)
        {
            --m_top;
            ret = (m_buffer+m_top);
        }

        return ret;
    }

    T&  at(int pos)
    {
        return (*this)[pos];
    }

    T&  operator [](int pos)
    {
        if(pos >= m_size)
        {
            reAlloc(m_size + DVECTOR_INC_SIZE);
        }

        return m_buffer[pos];
    }

    void    clear()
    {
        m_top = 0;
    }

    int getSize()
    {
        return m_size;
    }

    int     getTop()
    {
        return m_top;
    }
    
    bool    empty()
    {
        return 0 == m_top;
    }

    void    reAlloc(int ASize)
    {
        if(ASize > 0)
        {
            T*  pNewBuffer = new T[ASize];
            if(NULL != pNewBuffer)
            {
                if(NULL != m_buffer)
                {
                    memmove(pNewBuffer, m_buffer, sizeof(T)*m_top);
                    delete []m_buffer;
                }

                m_buffer = pNewBuffer;
                m_size = ASize;
            }
        }
    }

private:
    int m_size;
    int m_top;
    T*  m_buffer;
};

//管理缓冲区的类,具有读写指针
class MagicType
{
public:
    MagicType(bool bIncrease = true) : m_canIncrease(bIncrease)
    {
        init();
        m_buffer = NULL;
        m_size = 0;
    }

    virtual ~MagicType()
    {
        if (m_canIncrease)
        {
            if(NULL != m_buffer)
            {
                delete []m_buffer;
                m_buffer = NULL;
            }
        }
    }

    inline void    init()
    {
        m_readPos = 0;
        m_writePos = 0;
    }

    template<typename T>
    T*  readTypePtr()
    {
        if(sizeof(T) + m_readPos > m_writePos)
            return NULL;
        T*  ret = (T*)&m_buffer[m_readPos];
        addReadPos(sizeof(T));
        return ret;
    }


    template<typename T>
    T&    readRef()
    {
        T&  ret = *(T*)&m_buffer[m_readPos];
        addReadPos(sizeof(T));
        return ret;
    }

    template<typename T>
    T&      popWriteRef()
    {
        if (sizeof(T) + m_writePos > m_size)
        {
            increaseBuffer(sizeof(T));
        }

        T& RET = popWriteTypeRefFromBuffer<T>(getWriteBuffer());
        addWritePos(sizeof(T));
        return RET;
    }

    template<typename T>
    void    writeValue(T aData)
    {
        writeBuffer((char*)&aData, sizeof(T));
    }

    template<typename T>
    void writeRef(T& aData)
    {
        writeBuffer((char*)&aData, sizeof(T));
    }

    void    addReadPos(size_t aReadPos)
    {
        m_readPos += aReadPos;
    }

    int            getReadPos()
    {
        return m_readPos;
    }

    int        getWritePos()
    {
        return m_writePos;
    }

    void        addWritePos(size_t aWritePos)
    {
        m_writePos += aWritePos;
    }

    void        writeBuffer(const char* aBuffer, size_t aLength)
    {
        if(m_writePos + aLength > m_size)
        {
            increaseBuffer(aLength);
        }

        if(m_writePos + aLength <= m_size)
        {
            memcpy(m_buffer + m_writePos, aBuffer, aLength);
            addWritePos(aLength);
        }
    }

    inline int    getUsableSize()
    {
        return m_writePos - m_readPos;
    }

    inline size_t    getSize()
    {
        return m_size;
    }


    inline char*    getReadBuffer()
    {
        return m_buffer + m_readPos;
    }

    inline char*    getWriteBuffer()
    {
        return m_buffer + m_writePos;
    }

    inline char*   getBuffer()
    {
        return m_buffer;
    }

    inline void     adjustToHead()
    {
        m_writePos -= m_readPos;
        memmove(m_buffer, m_buffer + m_readPos, m_writePos);
        m_readPos = 0;

    }

protected:

    void    reAlloc(size_t aSize)
    {
        if (m_canIncrease)
        {
            char* newMemory = new char[aSize];
            if(NULL != newMemory)
            {
                if(NULL != m_buffer)
                {
                    memcpy(newMemory, m_buffer + m_readPos, m_writePos - m_readPos);
                    delete []m_buffer;
                    m_buffer = NULL;
                }
                m_buffer = newMemory;
                m_size = aSize;
                m_writePos -= m_readPos;
                m_readPos = 0;
            }
        }
    }

private:
    void    increaseBuffer(size_t    aLength)
    {
        if(m_writePos + aLength > m_size)
        {
            size_t TempLenght = m_writePos + aLength - m_readPos;
            if (TempLenght <= m_size)
            {
                memmove(m_buffer, m_buffer + m_readPos, m_writePos - m_readPos);
                m_writePos -= m_readPos;
                m_readPos = 0;
            }
            else
            {
                if (m_canIncrease)
                {
                    reAlloc(TempLenght);
                }
            }
        }
    }

protected:
    const bool        m_canIncrease;
    char*        m_buffer;

private:
    size_t        m_readPos;
    size_t        m_writePos;

protected:
    size_t        m_size;
};

class BufferIterator
{
public:
    BufferIterator(char* pBuffer)
    {
        m_startBuffer = m_currentBuffer = pBuffer;
        m_pos = 0;
    }

    template<typename T>
    inline T&    readRef()
    {
        T& RET = popWriteTypeRefFromBuffer<T>(m_currentBuffer);
        m_currentBuffer += sizeof(T);
        m_pos += sizeof(T);
        return RET;
    }

    inline    char*    getStartBuffer()
    {
        return m_startBuffer;
    }

    inline    char*    getCurrentBuffer()
    {
        return m_currentBuffer;
    }

    inline void    addPos(int aAdd)
    {
        m_currentBuffer += aAdd;
        m_pos += aAdd;
    }

    inline size_t        getPos()
    {
        return m_pos;
    }

private:
    char*            m_currentBuffer;
    char*            m_startBuffer;
    size_t            m_pos;
};

//使用动态分配内存区域
template<size_t SIZE>
class SizeMagicType : public virtual MagicType
{
public:
    SizeMagicType()
    {
        reAlloc(SIZE);
    }
};

//使用定长内存区域,禁止自动增长
template<size_t SIZE>
class FixedSizeType : public virtual MagicType
{
public:
    FixedSizeType() : MagicType(false)
    {
        m_buffer = m_realBuffer;
        m_size = SIZE;
        memset(m_realBuffer, 0, sizeof(m_realBuffer));
    }

private:
    char    m_realBuffer[SIZE];
};

template<typename T, bool AUTOINC = false>  //AUTOINC参数表示是否需要缓冲池自动增长
class TypePool
{
public:
    typedef T   ELEMENTTYPE;

    TypePool(int SIZE = 0)
    {
        m_memory = NULL;
        m_ptrArray = NULL;
        m_ptrArraySize = 0;

        init(SIZE);
    }

    ~TypePool()
    {
        if (NULL != m_memory)
        {
            delete []m_memory;
        }
        m_memory = NULL;

        if(NULL != m_ptrArray)
        {
            delete []m_ptrArray;
        }
        m_ptrArray = NULL;
        m_ptrArraySize = 0;
    }

    void    init(int aSize)
    {
        if(aSize > 0)
        {
            if (NULL != m_memory)
            {
                delete []m_memory;
            }

            if(NULL != m_ptrArray)
            {
                delete []m_ptrArray;
                m_ptrArraySize = 0;
            }

            m_memory = new T[aSize];
            m_ptrArray = new T*[aSize];
            m_memorySize = aSize;
            m_ptrArraySize = 0;
        }

        if(NULL != m_memory)
        {
            for(int i = 0; i < aSize; ++i)
            {
                pushPtrElement(&(m_memory[i]));
            }
        }
    }


    ELEMENTTYPE* popPtrElement()
    {
        ELEMENTTYPE* ret = NULL;

        if(m_ptrArraySize > 0)
        {
            ret = m_ptrArray[--m_ptrArraySize];
        }

        return ret;
    }

    T*  getMemory()
    {
        return m_memory;
    }

    void pushPtrElement(ELEMENTTYPE* p)
    {
        if (NULL != p && m_ptrArraySize < m_memorySize)
        {
            m_ptrArray[m_ptrArraySize++] = p;
        }
    }

private:
    T*              m_memory;
    int             m_memorySize;

    T**             m_ptrArray;
    int             m_ptrArraySize;
};

template<typename T>
class TypePool<T, true>
{
public:
    typedef T   ELEMENTTYPE;
    TypePool(int SIZE = 0)
    {
        baseBuffer = NULL;
        init(SIZE);
    }

    ~TypePool()
    {
        if(NULL != baseBuffer)
        {
            delete[] baseBuffer;
            baseBuffer = NULL;
        }
        
        ELEMENTTYPE** temp = NULL;
        while(temp = m_dynamicMemory.pop_back())
        {
            delete (*temp);
            temp = NULL;
        }
        
    }
    void    init(int ASize)
    {
        if(!baseBuffer && ASize > 0)
        {
            baseBuffer = new ELEMENTTYPE[ASize];
            if(NULL != baseBuffer)
            {
                m_memory.reAlloc(ASize);
                for(int i = 0; i < ASize; ++i)
                {
                    m_memory.push_back(baseBuffer+i);
                }
            }
        }
    }

    ELEMENTTYPE* popPtrElement()
    {
        ELEMENTTYPE** pp = m_memory.pop_back();
        if(NULL != pp)
        {
            return *pp;
        }
        else
        {
            ELEMENTTYPE* p = new ELEMENTTYPE();
            if(NULL != p)
            {
                m_dynamicMemory.push_back(p);
            }
            
            return p;
        }
    }

    void pushPtrElement(ELEMENTTYPE* p)
    {
        m_memory.push_back(p);
    }
private:
    DVector<T*> m_memory;
    DVector<T*> m_dynamicMemory;
    ELEMENTTYPE*    baseBuffer;
};

template<typename _T>
class Singleton
{
public:
    typedef    _T    T;
    inline static void StaticDestroy()
    {
        delete g_pInstance;
        g_pInstance = NULL;
    }
    inline static void StaticInit()
    {
        if (NULL == g_pInstance)
        {
            g_pInstance = new T;
        }
    }
    inline static T* GetInstance()
    {
        if (NULL == g_pInstance)
        {
            StaticInit();
        }
        return g_pInstance;
    }

public:
    //friend    T;        //gcc error
    static T* g_pInstance;
    Singleton( void )
    {
    }
    virtual ~Singleton( void )
    {
    }
};
}


#endif
